import type { SerialTaskExecuteContext } from '../handler'
import { SerialHandler } from '../handler'
import { chunkArray } from '../utils'

class SplitAudio extends SerialHandler<Array<number>, Array<number>> {
  public static readonly SPLIT_SIZE = 1280

  public static readonly INTERVAL_TIME = 25

  private lastRemainingAudioData: Array<number> = []

  private exportTimer: NodeJS.Timeout | null = null

  public execute(
    context: SerialTaskExecuteContext<Array<number>, Array<number>>,
  ): void {
    let originalAudioData = []
    if (context.isLastExecute) {
      originalAudioData = [...this.lastRemainingAudioData]
    }
    else {
      originalAudioData = [...this.lastRemainingAudioData, ...context.taskItem.original!]
    }

    const audioDataChunks = chunkArray(originalAudioData, SplitAudio.SPLIT_SIZE) || []

    if (audioDataChunks.length) {
      if (audioDataChunks[audioDataChunks.length - 1].length < SplitAudio.SPLIT_SIZE) {
        this.lastRemainingAudioData = audioDataChunks.pop()!
      }

      let chunkIndex = 0
      this.exportTimer = setInterval(() => {
        if (chunkIndex < audioDataChunks.length) {
          this.forwardToHandler(audioDataChunks[chunkIndex])
          chunkIndex += 1
        }
        else {
          if (this.exportTimer) {
            clearInterval(this.exportTimer)
          }
          this.exportTimer = null
          chunkIndex = 0

          this.taskCompletedCallback()
        }
      }, SplitAudio.INTERVAL_TIME)
    }
    else {
      console.error(this.isHandleDataAcceptedComplete)
      this.taskCompletedCallback()
    }
  }

  protected onFinish(): void {
    this.lastRemainingAudioData = []
    if (this.exportTimer) {
      clearInterval(this.exportTimer)
    }
    this.exportTimer = null

    this.executeController?.$bus.emit('_splitAudioFinish')
  }
}

export default SplitAudio
